package com.ruoyi.framework.web.service;


import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.DeviceConstants;
import com.ruoyi.common.constant.LoginConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.YxAndroidDeviceVo;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.wx.Jcode2SessionUtil;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.domain.AndroidDeviceVo;
import com.ruoyi.system.domain.AndroidDevice;
import com.ruoyi.system.domain.YxDeviceAndGetui;
import com.ruoyi.system.domain.YxDeviceExtraInfo;
import com.ruoyi.system.domain.YxUserAndDevice;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.impl.SysUserServiceImpl;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 微信业务实现类
 */
@Component
public class DeviceService {

    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Value("${weChat.appid}")
    private String appid;

    @Value("${weChat.secret}")
    private String secret;

    @Autowired
    private RedisCache redisUtil;

    @Autowired
    private TokenService tokenService;

    @Resource
    private IYxDeviceAndGetuiService yxDeviceAndGetuiService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IAndroidDeviceService androidDeviceService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private IYxUserAndDeviceService yxUserAndDeviceService;

    @Autowired
    private IYxDeviceExtraInfoService yxDeviceExtraInfoService;



    public R<String> login(AndroidDeviceVo androidDeviceVo) throws Exception{

        // 从数据库获取用户信息
        AndroidDevice query = new AndroidDevice();
        query.setDeviceId(androidDeviceVo.getDeviceId());
        List<AndroidDevice> deviceList = androidDeviceService.selectAndroidDeviceList(query);

        if(deviceList != null && deviceList.size() == 1){
            AndroidDevice wxUser = deviceList.get(0);
            SysUser sysUser = userService.selectUserById(wxUser.getUserId());
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            LoginUser loginUser = createLoginUser(sysUser);
            recordLoginInfo(loginUser.getUserId());
            // 生成token
            String token = tokenService.createToken(loginUser);
            // 登录成功
            return R.ok(token);
        }


        return R.fail("用户未注册");
    }

    public R<String> bindCid(String cid) throws Exception{

        if(TextUtils.isEmpty(cid)){
            return R.fail("cid 不可为空");
        }
        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        log.debug( "bindCid  userid ：" + user.getUserId());
        SysUser indb = userService.selectUserById(user.getUserId());
        if(indb == null || indb.getAccountType() != LoginConstants.USER_TYPE_DEVICE_STU){
            return R.fail("设备信息异常");
        }

        AndroidDevice query = new AndroidDevice();
        query.setDeviceId(indb.getUserName());
        List<AndroidDevice> androidDeviceList = androidDeviceService.selectAndroidDeviceList(query);
        if(androidDeviceList == null || androidDeviceList.size() != 1){
            return R.fail("设备信息异常");
        }

        //查询是否有历史记录
        YxDeviceAndGetui queryGetui = new YxDeviceAndGetui();
        queryGetui.setDeviceId(indb.getUserName());
        List<YxDeviceAndGetui> list = yxDeviceAndGetuiService.selectYxDeviceAndGetuiList(queryGetui);

        if(list != null && list.size() == 1){
            // 更新历史记录
            list.get(0).setCid(cid);
            yxDeviceAndGetuiService.updateYxDeviceAndGetui(list.get(0));
        }else {
            // 插入新记录
            YxDeviceAndGetui yxDeviceAndGetui = new YxDeviceAndGetui();
            yxDeviceAndGetui.setCid(cid);
            yxDeviceAndGetui.setDeviceId(indb.getUserName());
            yxDeviceAndGetuiService.insertYxDeviceAndGetui(yxDeviceAndGetui);
        }

        return R.ok("绑定成功");
    }

    public R<String> register(AndroidDeviceVo androidDeviceVo) throws Exception{

        // 从数据库获取用户信息
        AndroidDevice query = new AndroidDevice();
        query.setDeviceId(androidDeviceVo.getDeviceId());
        List<AndroidDevice> deviceList = androidDeviceService.selectAndroidDeviceList(query);


        // 二次注册 直接登录。
        if(deviceList != null && deviceList.size() == 1){
            AndroidDevice wxUser = deviceList.get(0);
            SysUser sysUser = userService.selectUserById(wxUser.getUserId());
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            LoginUser loginUser = createLoginUser(sysUser);
            recordLoginInfo(loginUser.getUserId());
            // 生成token
            String token = tokenService.createToken(loginUser);
            // 登录成功
            return R.ok(token);
        }

        if(deviceList == null || deviceList.size() == 0){
            //首次登录 用户注册

            SysUser sysUser = userService.selectUserByUserName(androidDeviceVo.getDeviceId());
            if(sysUser == null){
                // 如何没有历史数据 则 先创建SysUser
                sysUser = new SysUser();
                sysUser.setUserName(androidDeviceVo.getDeviceId());
                sysUser.setNickName("测试");
                sysUser.setAccountType(LoginConstants.USER_TYPE_DEVICE_STU);
                userService.insertUser(sysUser);
            }

            sysUser = userService.selectUserByUserName(androidDeviceVo.getDeviceId());

            //再创建wxuser
            AndroidDevice insertDevice = new AndroidDevice();
            insertDevice.setDeviceId(androidDeviceVo.getDeviceId());
            insertDevice.setCreateTime(new Date());
            insertDevice.setUserId(sysUser.getUserId());
            insertDevice.setManufacturer(androidDeviceVo.getManufacturer());
            insertDevice.setMac(androidDeviceVo.getMac());
            insertDevice.setModel(androidDeviceVo.getModel());
            insertDevice.setOsVersion(androidDeviceVo.getOsVersion());
            insertDevice.setScreenSize(androidDeviceVo.getScreenSize());
            insertDevice.setStorage(androidDeviceVo.getStorage());
            insertDevice.setRam(androidDeviceVo.getRam());
            insertDevice.setSn(androidDeviceVo.getSn());
            androidDeviceService.insertAndroidDevice(insertDevice);


            query = new AndroidDevice();
            query.setDeviceId(androidDeviceVo.getDeviceId());
            deviceList = androidDeviceService.selectAndroidDeviceList(query);

            // 生成额外字段
            YxDeviceExtraInfo yxDeviceExtraInfo = new YxDeviceExtraInfo();
            yxDeviceExtraInfo.setDeviceId(androidDeviceVo.getDeviceId());
            yxDeviceExtraInfo.setdId(deviceList.get(0).getId());
            yxDeviceExtraInfo.setCreateTime(new Date());
            yxDeviceExtraInfoService.insertYxDeviceExtraInfo(yxDeviceExtraInfo);

            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            LoginUser loginUser = createLoginUser(sysUser);
            recordLoginInfo(loginUser.getUserId());
            // 生成token
            String token = tokenService.createToken(loginUser);
            // 登录成功
            return R.ok(token);
        }


        return R.fail("用户未注册");

    }

    /**
     * 登录凭证校验
     * @param code
     * @return
     * @throws Exception
     */
    private String jcode2Session(String code)throws Exception{
        String sessionInfo = Jcode2SessionUtil.jscode2session(appid,secret,code,"authorization_code");//登录grantType固定
        return sessionInfo;
    }

    public LoginUser createLoginUser(SysUser user)
    {
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

    public R<String> getUuui2BindUser() {

        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();
        return wxGetUuui2BindUser(user.getUserName());
    }

    public R<String> wxGetUuui2BindUser(String deviceId) {

        //先清除之前缓存数据
        String oldUuid = redisUtil.getCacheObject(CacheConstants.DEVICE_BIND_USER_KEY + deviceId);
        if(!StringUtils.isEmpty(oldUuid)){
            redisUtil.deleteObject(CacheConstants.DEVICE_BIND_USER_KEY + oldUuid);
        }
        redisUtil.deleteObject(CacheConstants.DEVICE_BIND_USER_KEY + deviceId);

        //重新生成uuid
        String uuid = UUID.randomUUID().toString();
        redisUtil.setCacheObject(CacheConstants.DEVICE_BIND_USER_KEY + uuid,deviceId ,5, TimeUnit.MINUTES);
        redisUtil.setCacheObject(CacheConstants.DEVICE_BIND_USER_KEY + deviceId,uuid ,5, TimeUnit.MINUTES);
        return R.ok(uuid);
    }

    public R<List<YxAndroidDeviceVo>> getDeviceList() {
        // 获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 获取 设备列表
        YxUserAndDevice query = new YxUserAndDevice();
        query.setUserId(user.getUserId());
        List<YxAndroidDeviceVo> yxUserAndDeviceList= yxUserAndDeviceService.selectYxAndroidDeviceVoList(user.getUserId());
        if(yxUserAndDeviceList == null || yxUserAndDeviceList.size() == 0){
            return R.fail("当前用户暂无绑定设备");
        }
        return R.ok(yxUserAndDeviceList);
    }

    public YxUserAndDevice getDefaultDevice() {

        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        //获取当前默认绑定设备
        YxUserAndDevice query = new YxUserAndDevice();
        query.setUserId(user.getUserId());
        query.setIsDefult(DeviceConstants.USER_DEFULT_DEVICE);
        List<YxUserAndDevice> yxUserAndDeviceList= yxUserAndDeviceService.selectYxUserAndDeviceList(query);
        if(yxUserAndDeviceList == null || yxUserAndDeviceList.size() != 1){
            return null;
        }

        // 查询数据
        return yxUserAndDeviceList.get(0);

    }

    public R<String> editStuName(Long dId, String stuName) {
        if(null == dId || 0 == dId){
            return R.fail("dId 不可为空");
        }
        if(TextUtils.isEmpty(stuName)){
            return R.fail("stuName 不可为空");
        }
        // 获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        AndroidDevice androidDevice = androidDeviceService.selectAndroidDeviceById(dId);
        if(androidDevice == null){
            return R.fail("dId 不存在");
        }

        YxDeviceExtraInfo query = new YxDeviceExtraInfo();
        query.setdId(dId);
        List<YxDeviceExtraInfo> list = yxDeviceExtraInfoService.selectYxDeviceExtraInfoList(query);
        if(list == null || list.size() == 0){
            return R.fail("设备异常。请联系管理员");
        }

        YxDeviceExtraInfo yxDeviceExtraInfo = list.get(0);
        yxDeviceExtraInfo.setStuName(stuName);
        yxDeviceExtraInfoService.updateYxDeviceExtraInfo(yxDeviceExtraInfo);

        return R.ok();
    }

    public R<String> switchDefaultDevice(Long dId) {
        if(null == dId || 0 == dId){
            return R.fail("dId 不可为空");
        }

        AndroidDevice androidDevice = androidDeviceService.selectAndroidDeviceById(dId);
        if(androidDevice == null){
            return R.fail("dId 不存在");
        }

        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 1、查询之前是否绑定
        YxUserAndDevice query = new YxUserAndDevice();
        query.setUserId(user.getUserId());
        List<YxUserAndDevice> list = yxUserAndDeviceService.selectYxUserAndDeviceList(query);
        if(list == null || list.size() == 0){
            return R.fail("该设备未绑定，请先绑定设备");
        }

        boolean isHaveDevice = false;

        for(YxUserAndDevice yxUserAndDevice : list){
            if(yxUserAndDevice.getDeviceId().equals(androidDevice.getDeviceId())){
                yxUserAndDevice.setIsDefult(DeviceConstants.USER_DEFULT_DEVICE);
                isHaveDevice = true;
            }else {
                yxUserAndDevice.setIsDefult(DeviceConstants.USER_NO_DEFULT_DEVICE);
            }
        }
        if(!isHaveDevice){
            return R.fail("该设备未绑定，请先绑定设备");
        }

        //更新数据库
        for(YxUserAndDevice yxUserAndDevice : list) {
            yxUserAndDeviceService.updateYxUserAndDevice(yxUserAndDevice);
        }

        return R.ok();
    }

    public R<String> unBindDevice(Long dId) {
        if(null == dId || 0 == dId){
            return R.fail("dId 不可为空");
        }

        AndroidDevice androidDevice = androidDeviceService.selectAndroidDeviceById(dId);
        if(androidDevice == null){
            return R.fail("dId 不存在");
        }

        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 1、查询之前是否绑定
        YxUserAndDevice query = new YxUserAndDevice();
        query.setUserId(user.getUserId());
        query.setDeviceId(androidDevice.getDeviceId());
        List<YxUserAndDevice> list = yxUserAndDeviceService.selectYxUserAndDeviceList(query);
        if(list == null || list.size() != 1){
            return R.fail("该设备未绑定");
        }

        boolean isDelelDefult = DeviceConstants.USER_DEFULT_DEVICE.equals(list.get(0).getIsDefult());

        // 更新数据库 删除 绑定关系
        yxUserAndDeviceService.deleteYxUserAndDeviceById(list.get(0).getId());

        YxUserAndDevice queryNew = new YxUserAndDevice();
        queryNew.setUserId(user.getUserId());
        list = yxUserAndDeviceService.selectYxUserAndDeviceList(queryNew);

        // 如何删除的是默认设备  且剩余的设备数大于1 则自动将最后一台设备更新为默认设备
        if(isDelelDefult && list != null && list.size() > 0 ){
            list.get(0).setIsDefult(DeviceConstants.USER_DEFULT_DEVICE);
            yxUserAndDeviceService.updateYxUserAndDevice(list.get(0));
        }


        return R.ok();
    }



    public R<Map> wxDeviceInfo() {

        // 获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 获取当前默认绑定设备
        YxUserAndDevice query = new YxUserAndDevice();
        query.setUserId(user.getUserId());
        query.setIsDefult(DeviceConstants.USER_DEFULT_DEVICE);
        List<YxUserAndDevice> yxUserAndDeviceList= yxUserAndDeviceService.selectYxUserAndDeviceList(query);
        if(yxUserAndDeviceList == null || yxUserAndDeviceList.size() != 1){
            return R.fail("当前用户暂无绑定设备");
        }


        YxDeviceExtraInfo query3 = new YxDeviceExtraInfo();
        query3.setDeviceId(yxUserAndDeviceList.get(0).getDeviceId());
        List<YxDeviceExtraInfo> list3 = yxDeviceExtraInfoService.selectYxDeviceExtraInfoList(query3);

        Map<String,Object> returnMap = new HashMap<>();
        if(list3 == null || list3.size() == 0){
            returnMap.put("controlMode",0);
            returnMap.put("stuName","");
            returnMap.put("isLockScreen",false);
        }else {
            returnMap.put("controlMode",list3.get(0).getControlMode());
            returnMap.put("stuName",list3.get(0).getStuName());
            returnMap.put("isLockScreen",list3.get(0).getIsLockScreen() == null ? 0 : list3.get(0).getIsLockScreen() == 1);
        }

        return R.ok(returnMap);
    }
}
